/*
 * Copyright (C) 2021-2025 The FlorisBoard Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dev.patrickgold.florisboard.app.settings.localization

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.lifecycle.Observer
import androidx.lifecycle.compose.LocalLifecycleOwner
import dev.patrickgold.florisboard.R
import dev.patrickgold.florisboard.app.FlorisPreferenceStore
import dev.patrickgold.florisboard.app.LocalNavController
import dev.patrickgold.florisboard.app.Routes
import dev.patrickgold.florisboard.ime.core.DisplayLanguageNamesIn
import dev.patrickgold.florisboard.ime.core.Subtype
import dev.patrickgold.florisboard.ime.core.SubtypeJsonConfig
import dev.patrickgold.florisboard.ime.core.SubtypeLayoutMap
import dev.patrickgold.florisboard.ime.core.SubtypeNlpProviderMap
import dev.patrickgold.florisboard.ime.core.SubtypePreset
import dev.patrickgold.florisboard.ime.keyboard.LayoutArrangementComponent
import dev.patrickgold.florisboard.ime.keyboard.LayoutType
import dev.patrickgold.florisboard.ime.keyboard.extCorePopupMapping
import dev.patrickgold.florisboard.ime.nlp.han.HanShapeBasedLanguageProvider
import dev.patrickgold.florisboard.ime.nlp.han.HanPinyinLanguageProvider
import dev.patrickgold.florisboard.ime.nlp.latin.LatinLanguageProvider
import dev.patrickgold.florisboard.keyboardManager
import dev.patrickgold.florisboard.lib.FlorisLocale
import dev.patrickgold.florisboard.lib.compose.FlorisScreen
import dev.patrickgold.florisboard.lib.ext.ExtensionComponentName
import dev.patrickgold.florisboard.lib.observeAsNonNullState
import dev.patrickgold.florisboard.subtypeManager
import dev.patrickgold.jetpref.datastore.model.observeAsState
import dev.patrickgold.jetpref.material.ui.JetPrefAlertDialog
import dev.patrickgold.jetpref.material.ui.JetPrefDropdown
import dev.patrickgold.jetpref.material.ui.JetPrefDropdownMenuDefaults
import dev.patrickgold.jetpref.material.ui.JetPrefListItem
import org.florisboard.lib.compose.FlorisButtonBar
import org.florisboard.lib.compose.FlorisDropdownLikeButton
import org.florisboard.lib.compose.florisScrollbar
import org.florisboard.lib.compose.stringRes


private val SelectComponentName = ExtensionComponentName("00", "00")
private val SelectNlpProviderId = SelectComponentName.toString()
private val SelectNlpProviders = SubtypeNlpProviderMap(
    spelling = SelectNlpProviderId,
)
private val SelectLayoutMap = SubtypeLayoutMap(
    characters = SelectComponentName,
    symbols = SelectComponentName,
    symbols2 = SelectComponentName,
    numeric = SelectComponentName,
    numericAdvanced = SelectComponentName,
    numericRow = SelectComponentName,
    phone = SelectComponentName,
    phone2 = SelectComponentName,
)
private val SelectLocale = FlorisLocale.from("00", "00")
private val SelectListKeys = listOf(SelectComponentName)

private class SubtypeEditorState(init: Subtype?) {
    companion object {
        val Saver = Saver<SubtypeEditorState, String>(
            save = { editor ->
                val subtype = Subtype(
                    id = editor.id.value,
                    primaryLocale = editor.primaryLocale.value,
                    secondaryLocales = editor.secondaryLocales.value,
                    nlpProviders = editor.nlpProviders.value,
                    composer = editor.composer.value,
                    currencySet = editor.currencySet.value,
                    punctuationRule = editor.punctuationRule.value,
                    popupMapping = editor.popupMapping.value,
                    layoutMap = editor.layoutMap.value,
                )
                SubtypeJsonConfig.encodeToString(subtype)
            },
            restore = { str ->
                val subtype = SubtypeJsonConfig.decodeFromString<Subtype>(str)
                SubtypeEditorState(subtype)
            },
        )
    }

    val id: MutableState<Long> = mutableLongStateOf(init?.id ?: -1)
    val primaryLocale: MutableState<FlorisLocale> = mutableStateOf(init?.primaryLocale ?: SelectLocale)
    val secondaryLocales: MutableState<List<FlorisLocale>> = mutableStateOf(init?.secondaryLocales ?: listOf())
    val nlpProviders: MutableState<SubtypeNlpProviderMap> = mutableStateOf(init?.nlpProviders ?: Subtype.DEFAULT.nlpProviders)
    val composer: MutableState<ExtensionComponentName> = mutableStateOf(init?.composer ?: SelectComponentName)
    val currencySet: MutableState<ExtensionComponentName> = mutableStateOf(init?.currencySet ?: SelectComponentName)
    val punctuationRule: MutableState<ExtensionComponentName> = mutableStateOf(init?.punctuationRule ?: Subtype.DEFAULT.punctuationRule)
    val popupMapping: MutableState<ExtensionComponentName> = mutableStateOf(init?.popupMapping ?: SelectComponentName)
    val layoutMap: MutableState<SubtypeLayoutMap> = mutableStateOf(init?.layoutMap ?: SelectLayoutMap)

    fun applySubtype(subtype: Subtype) {
        id.value = subtype.id
        primaryLocale.value = subtype.primaryLocale
        secondaryLocales.value = subtype.secondaryLocales
        composer.value = subtype.composer
        nlpProviders.value = subtype.nlpProviders
        currencySet.value = subtype.currencySet
        punctuationRule.value = subtype.punctuationRule
        popupMapping.value = subtype.popupMapping
        layoutMap.value = subtype.layoutMap
    }

    fun toSubtype() = runCatching<Subtype> {
        check(primaryLocale.value != SelectLocale)
        check(nlpProviders.value.spelling != SelectNlpProviderId)
        check(nlpProviders.value.suggestion != SelectNlpProviderId)
        check(composer.value != SelectComponentName)
        check(currencySet.value != SelectComponentName)
        check(punctuationRule.value != SelectComponentName)
        check(popupMapping.value != SelectComponentName)
        check(layoutMap.value.characters != SelectComponentName)
        check(layoutMap.value.symbols != SelectComponentName)
        check(layoutMap.value.symbols2 != SelectComponentName)
        check(layoutMap.value.numeric != SelectComponentName)
        check(layoutMap.value.numericAdvanced != SelectComponentName)
        check(layoutMap.value.numericRow != SelectComponentName)
        check(layoutMap.value.phone != SelectComponentName)
        check(layoutMap.value.phone2 != SelectComponentName)
        Subtype(
            id.value, primaryLocale.value, secondaryLocales.value, nlpProviders.value, composer.value,
            currencySet.value, punctuationRule.value, popupMapping.value, layoutMap.value,
        )
    }
}

@Composable
fun SubtypeEditorScreen(id: Long?) = FlorisScreen {
    title = stringRes(if (id == null) {
        R.string.settings__localization__subtype_add_title
    } else {
        R.string.settings__localization__subtype_edit_title
    })

    val selectValue = stringRes(R.string.settings__localization__subtype_select_placeholder)
    val selectListValues = remember(selectValue) { listOf(selectValue) }

    val prefs by FlorisPreferenceStore
    val navController = LocalNavController.current
    val context = LocalContext.current
    val configuration = LocalConfiguration.current
    val lifecycleOwner = LocalLifecycleOwner.current
    val keyboardManager by context.keyboardManager()
    val subtypeManager by context.subtypeManager()

    val displayLanguageNamesIn by prefs.localization.displayLanguageNamesIn.observeAsState()
    val composers by keyboardManager.resources.composers.observeAsNonNullState()
    val currencySets by keyboardManager.resources.currencySets.observeAsNonNullState()
    val layoutExtensions by keyboardManager.resources.layouts.observeAsNonNullState()
    val popupMappings by keyboardManager.resources.popupMappings.observeAsNonNullState()
    val subtypePresets by keyboardManager.resources.subtypePresets.observeAsNonNullState()

    val subtypeEditor = rememberSaveable(saver = SubtypeEditorState.Saver) {
        val subtype = id?.let { subtypeManager.getSubtypeById(id) }
        SubtypeEditorState(subtype)
    }
    var primaryLocale by subtypeEditor.primaryLocale
    //var secondaryLocales by subtypeEditor.secondaryLocales
    var composer by subtypeEditor.composer
    var currencySet by subtypeEditor.currencySet
    var popupMapping by subtypeEditor.popupMapping
    var layoutMap by subtypeEditor.layoutMap
    var nlpProviders by subtypeEditor.nlpProviders

    var showSubtypePresetsDialog by rememberSaveable { mutableStateOf(id == null) }
    var showSelectAsError by rememberSaveable { mutableStateOf(false) }
    var errorDialogStrId by rememberSaveable { mutableStateOf<Int?>(null) }

    val selectLocaleScreenResult = navController.currentBackStackEntry
        ?.savedStateHandle
        ?.getLiveData<String>(SelectLocaleScreenResultLanguageTag)
    DisposableEffect(selectLocaleScreenResult, lifecycleOwner) {
        val observer = Observer<String> { languageTag ->
            val locale = FlorisLocale.fromTag(languageTag)
            primaryLocale = locale
            val preset = subtypeManager.getSubtypePresetForLocale(locale)
            popupMapping = preset?.popupMapping ?: extCorePopupMapping("default")
        }
        selectLocaleScreenResult?.observe(lifecycleOwner, observer)
        onDispose { selectLocaleScreenResult?.removeObserver(observer) }
    }


    @Composable
    fun SubtypePropertyDropdown(
        title: String,
        layoutType: LayoutType,
    ) {
        SubtypeProperty(title) {
            SubtypeLayoutDropdown(
                layoutType = layoutType,
                layouts = layoutExtensions[layoutType] ?: mapOf(),
                showSelectAsError = showSelectAsError,
                layoutMap = layoutMap,
                onLayoutMapChanged = { layoutMap = it },
                selectListValues = selectListValues,
            )
        }
    }

    actions {
        if (id != null) {
            IconButton(onClick = {
                val subtype = subtypeManager.getSubtypeById(id)
                if (subtype != null) {
                    subtypeManager.removeSubtype(subtype)
                    navController.popBackStack()
                }
            }) {
                Icon(
                    imageVector = Icons.Default.Delete,
                    contentDescription = null,
                )
            }
        }
    }

    bottomBar {
        FlorisButtonBar {
            ButtonBarSpacer()
            ButtonBarTextButton(text = stringRes(R.string.action__cancel)) {
                navController.popBackStack()
            }
            ButtonBarButton(text = stringRes(R.string.action__save)) {
                subtypeEditor.toSubtype().onSuccess { subtype ->
                    if (id == null) {
                        if (!subtypeManager.addSubtype(subtype)) {
                            errorDialogStrId = R.string.settings__localization__subtype_error_already_exists
                            return@ButtonBarButton
                        }
                    } else {
                        subtypeManager.modifySubtypeWithSameId(subtype)
                    }
                    navController.popBackStack()
                }.onFailure {
                    showSelectAsError = true
                    errorDialogStrId = R.string.settings__localization__subtype_error_fields_no_value
                }
            }
        }
    }

    content {
        Column(modifier = Modifier.padding(8.dp)) {
            if (id == null) {
                Card(modifier = Modifier
                    .fillMaxWidth()
                    .padding(bottom = 16.dp),
                ) {
                    Column(modifier = Modifier.padding(vertical = 8.dp)) {
                        Text(
                            modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp),
                            text = stringRes(R.string.settings__localization__suggested_subtype_presets),
                            color = MaterialTheme.colorScheme.primary,
                            fontWeight = FontWeight.Bold,
                            maxLines = 1,
                            overflow = TextOverflow.Ellipsis,
                        )
                        val systemLocales = remember {
                            val list = mutableListOf<FlorisLocale>()
                            val localeList = configuration.locales
                            for (n in 0 until localeList.size()) {
                                list.add(FlorisLocale.from(localeList.get(n)))
                            }
                            list
                        }
                        val suggestedPresets = remember(subtypePresets) {
                            val presets = mutableListOf<SubtypePreset>()
                            for (systemLocale in systemLocales) {
                                subtypePresets.find { it.locale == systemLocale }?.let { presets.add(it) }
                            }
                            presets
                        }
                        if (suggestedPresets.isNotEmpty()) {
                            for (suggestedPreset in suggestedPresets) {
                                JetPrefListItem(
                                    modifier = Modifier.clickable {
                                        subtypeEditor.applySubtype(suggestedPreset.toSubtype())
                                    },
                                    text = when (displayLanguageNamesIn) {
                                        DisplayLanguageNamesIn.SYSTEM_LOCALE -> suggestedPreset.locale.displayName()
                                        DisplayLanguageNamesIn.NATIVE_LOCALE -> suggestedPreset.locale.displayName(suggestedPreset.locale)
                                    },
                                    secondaryText = suggestedPreset.preferred.characters.componentId,
                                    colors = ListItemDefaults.colors(containerColor = CardDefaults.cardColors().containerColor),
                                )
                            }
                        } else {
                            Text(
                                modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp),
                                text = stringRes(R.string.settings__localization__suggested_subtype_presets_none_found),
                            )
                        }
                        Button(
                            modifier = Modifier
                                .padding(horizontal = 16.dp)
                                .align(Alignment.End),
                            onClick = { showSubtypePresetsDialog = true },
                        ) {
                            Text(
                                text = stringRes(R.string.settings__localization__subtype_presets_view_all)
                            )
                        }
                    }
                }
            }

            SubtypeProperty(stringRes(R.string.settings__localization__subtype_locale)) {
                FlorisDropdownLikeButton(
                    item = if (primaryLocale == SelectLocale) selectValue else when (displayLanguageNamesIn) {
                        DisplayLanguageNamesIn.SYSTEM_LOCALE -> primaryLocale.displayName()
                        DisplayLanguageNamesIn.NATIVE_LOCALE -> primaryLocale.displayName(primaryLocale)
                    },
                    isError = showSelectAsError && primaryLocale == SelectLocale,
                    onClick = {
                        navController.navigate(Routes.Settings.SelectLocale)
                    },
                    appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
                )
            }
            SubtypeProperty(stringRes(R.string.settings__localization__subtype_popup_mapping)) {
                val popupMappingIds = remember(popupMappings) {
                    SelectListKeys + popupMappings.keys
                }
                
                // 添加中文标识的映射表 / Add Chinese labels mapping
                val popupMappingChineseLabels = mapOf(
                    "default" to "默认 (Default)",
                    "ar" to "阿拉伯语 (Arabic)",
                    "ast" to "阿斯图里亚斯语 (Asturian)",
                    "bg" to "保加利亚语 (Bulgarian)",
                    "bn-BD" to "孟加拉语 (Bengali)",
                    "ca" to "加泰罗尼亚语 (Catalan)",
                    "cjk" to "中日韩 (CJK)",
                    "ckb" to "中库尔德语 (Central Kurdish)",
                    "cs" to "捷克语 (Czech)",
                    "da" to "丹麦语 (Danish)",
                    "de" to "德语 (German)",
                    "de-DE-neobone" to "德语-Neobone (German-Neobone)",
                    "el" to "希腊语 (Greek)",
                    "en" to "英语 (English)",
                    "eo" to "世界语 (Esperanto)",
                    "es" to "西班牙语 (Spanish)",
                    "et" to "爱沙尼亚语 (Estonian)",
                    "fa" to "波斯语 (Persian)",
                    "fa2" to "波斯语2 (Persian 2)",
                    "fa3" to "波斯语3 (Persian 3)",
                    "fi" to "芬兰语 (Finnish)",
                    "fo" to "法罗语 (Faroese)",
                    "fr" to "法语 (French)",
                    "hi-IN" to "印地语 (Hindi)",
                    "hr" to "克罗地亚语 (Croatian)",
                    "hu" to "匈牙利语 (Hungarian)",
                    "hy" to "亚美尼亚语 (Armenian)",
                    "id" to "印尼语 (Indonesian)",
                    "is" to "冰岛语 (Icelandic)",
                    "it" to "意大利语 (Italian)",
                    "iw" to "希伯来语 (Hebrew)",
                    "ja-JP-jis" to "日语-JIS (Japanese-JIS)",
                    "kab" to "卡拜尔语 (Kabyle)",
                    "ko" to "韩语 (Korean)",
                    "ko-KR" to "韩语-韩国 (Korean-KR)",
                    "ku" to "库尔德语 (Kurdish)",
                    "lt" to "立陶宛语 (Lithuanian)",
                    "lv" to "拉脱维亚语 (Latvian)",
                    "nb" to "书面挪威语 (Norwegian Bokmål)",
                    "nn" to "新挪威语 (Norwegian Nynorsk)",
                    "pl" to "波兰语 (Polish)",
                    "pt" to "葡萄牙语 (Portuguese)",
                    "pt-BR" to "巴西葡萄牙语 (Brazilian Portuguese)",
                    "ro" to "罗马尼亚语 (Romanian)",
                    "ru" to "俄语 (Russian)",
                    "rue" to "卢森尼亚语 (Rusyn)",
                    "sk" to "斯洛伐克语 (Slovak)",
                    "sl-SI" to "斯洛文尼亚语 (Slovenian)",
                    "sr" to "塞尔维亚语 (Serbian)",
                    "sv" to "瑞典语 (Swedish)",
                    "tr" to "土耳其语 (Turkish)",
                    "udm" to "乌德穆尔特语 (Udmurt)",
                    "uk" to "乌克兰语 (Ukrainian)",
                    "uk-cyr-ext" to "乌克兰语-西里尔扩展 (Ukrainian-Cyr-Ext)",
                    "ur-PK" to "乌尔都语 (Urdu)",
                    "vi-VN" to "越南语 (Vietnamese)"
                )
                
                val popupMappingLabels = remember(popupMappings) {
                    selectListValues + popupMappings.keys.map { key ->
                        popupMappingChineseLabels[key.componentId] ?: key.componentId
                    }
                }
                val expanded = remember { mutableStateOf(false) }
                val selectedIndex = popupMappingIds.indexOf(popupMapping).coerceAtLeast(0)
                JetPrefDropdown(
                    options = popupMappingLabels,
                    expanded = expanded,
                    selectedOptionIndex = selectedIndex,
                    isError = showSelectAsError && selectedIndex == 0,
                    onSelectOption = { popupMapping = popupMappingIds[it] },
                    appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
                )
            }
            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_characters_layout), LayoutType.CHARACTERS)

            SubtypeGroupSpacer()

            SubtypeProperty(stringRes(R.string.settings__localization__subtype_suggestion_provider)) {
                // 添加中文标识 / Add Chinese labels
                val nlpProviderMappings = mapOf(
                    LatinLanguageProvider.ProviderId to "拉丁语系 (Latin)",
                    HanShapeBasedLanguageProvider.ProviderId to "中文形码 (Chinese shape-based)",
                    HanPinyinLanguageProvider.ProviderId to "中文拼音 (Chinese Pinyin)"  // 添加拼音选项
                )

                val nlpProviderMappingIds = remember(nlpProviderMappings) {
                    listOf(SelectNlpProviderId) + nlpProviderMappings.keys
                }
                val nlpProviderMappingLabels = remember(nlpProviderMappings) {
                    selectListValues + nlpProviderMappings.values.map { it }
                }
                val expanded = remember { mutableStateOf(false) }
                val selectedIndex = nlpProviderMappingIds.indexOf(nlpProviders.suggestion).coerceAtLeast(0)
                JetPrefDropdown(
                    options = nlpProviderMappingLabels,
                    expanded = expanded,
                    selectedOptionIndex = selectedIndex,
                    isError = showSelectAsError && selectedIndex == 0,
                    onSelectOption = { nlpProviders = SubtypeNlpProviderMap(
                        suggestion = nlpProviderMappingIds[it],
                        spelling = nlpProviderMappingIds[it]
                    ) },
                    appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
                )
            }

            SubtypeGroupSpacer()

            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_symbols_layout), LayoutType.SYMBOLS)
            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_symbols2_layout), LayoutType.SYMBOLS2)

            SubtypeProperty(stringRes(R.string.settings__localization__subtype_composer)) {
                val composerIds = remember(composers) {
                    SelectListKeys + composers.keys
                }
                
                // 添加中文标识 / Add Chinese labels
                val composerChineseLabels = mapOf(
                    "appender" to "追加器 (Appender)",
                    "hangul-unicode" to "韩文Unicode (Hangul-Unicode)",
                    "kana-unicode" to "假名Unicode (Kana-Unicode)",
                    "telex" to "Telex越南语 (Telex)"
                )
                
                val composerNames = remember(composers) {
                    selectListValues + composers.keys.map { key ->
                        composerChineseLabels[key.componentId] ?: composers[key]?.label ?: key.componentId
                    }
                }
                val expanded = remember { mutableStateOf(false) }
                JetPrefDropdown(
                    options = composerNames,
                    expanded = expanded,
                    selectedOptionIndex = composerIds.indexOf(composer).coerceAtLeast(0),
                    isError = showSelectAsError && composer == SelectComponentName,
                    onSelectOption = { composer = composerIds[it] },
                    appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
                )
            }
            SubtypeProperty(stringRes(R.string.settings__localization__subtype_currency_set)) {
                val currencySetIds = remember(currencySets) {
                    SelectListKeys + currencySets.keys
                }
                
                // 添加货币集中文标识 / Add Chinese labels for currency sets
                val currencyChineseNames = mapOf(
                    "dollar" to "美元",
                    "euro" to "欧元",
                    "pound" to "英镑",
                    "yen" to "日元/人民币",
                    "indian_rupee" to "印度卢比",
                    "russian_ruble" to "俄罗斯卢布",
                    "south_korean_won" to "韩元",
                    "pakistani_rupee" to "巴基斯坦卢比",
                    "bangladeshi_taka" to "孟加拉塔卡",
                    "thai_baht" to "泰铢",
                    "vietnamese_dong" to "越南盾",
                    "peso" to "比索",
                    "rial" to "里亚尔",
                    "armenian_dram" to "亚美尼亚德拉姆",
                    "azerbaijani_manat" to "阿塞拜疆马纳特",
                    "israeli_new_shekel" to "以色列新谢克尔",
                    "kazakhstani_tenge" to "哈萨克斯坦坚戈",
                    "turkish_lira" to "土耳其里拉",
                    "ukrainian_hryvnia" to "乌克兰格里夫纳",
                    "nigerian_naira" to "尼日利亚奈拉",
                    "paraguayan_guarani" to "巴拉圭瓜拉尼",
                    "mongolian_togrog" to "蒙古图格里克",
                    "lao_kip" to "老挝基普",
                    "costa_rican_colon" to "哥斯达黎加科朗",
                    "bitcoin" to "比特币"
                )
                
                val currencySetNames = remember(currencySets) {
                    selectListValues + currencySets.keys.map { key ->
                        val chineseName = currencyChineseNames[key.componentId]
                        val originalLabel = currencySets[key]?.label ?: key.componentId
                        if (chineseName != null) {
                            "$chineseName $originalLabel"
                        } else {
                            originalLabel
                        }
                    }
                }
                val expanded = remember { mutableStateOf(false) }
                JetPrefDropdown(
                    options = currencySetNames,
                    expanded = expanded,
                    selectedOptionIndex = currencySetIds.indexOf(currencySet).coerceAtLeast(0),
                    isError = showSelectAsError && currencySet == SelectComponentName,
                    onSelectOption = { currencySet = currencySetIds[it] },
                    appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
                )
            }

            SubtypeGroupSpacer()

            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_numeric_layout), LayoutType.NUMERIC)

            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_numeric_advanced_layout), LayoutType.NUMERIC_ADVANCED)

            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_numeric_row_layout), LayoutType.NUMERIC_ROW)

            SubtypeGroupSpacer()

            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_phone_layout), LayoutType.PHONE)

            SubtypePropertyDropdown(stringRes(R.string.settings__localization__subtype_phone2_layout), LayoutType.PHONE2)
        }

        if (showSubtypePresetsDialog) {
            JetPrefAlertDialog(
                title = stringRes(R.string.settings__localization__subtype_presets),
                dismissLabel = stringRes(android.R.string.cancel),
                scrollModifier = Modifier,
                contentPadding = PaddingValues(horizontal = 8.dp),
                onDismiss = {
                    showSubtypePresetsDialog = false
                },
            ) {
                Column {
                    HorizontalDivider()
                    val lazyListState = rememberLazyListState()
                    LazyColumn(
                        modifier = Modifier
                            .florisScrollbar(lazyListState, isVertical = true).weight(1f),
                        state = lazyListState,
                    ) {
                        items(subtypePresets) { subtypePreset ->
                            JetPrefListItem(
                                modifier = Modifier.clickable {
                                    subtypeEditor.applySubtype(subtypePreset.toSubtype())
                                    showSubtypePresetsDialog = false
                                },
                                text = when (displayLanguageNamesIn) {
                                    DisplayLanguageNamesIn.SYSTEM_LOCALE -> subtypePreset.locale.displayName()
                                    DisplayLanguageNamesIn.NATIVE_LOCALE -> subtypePreset.locale.displayName(subtypePreset.locale)
                                },
                                secondaryText = subtypePreset.preferred.characters.componentId,
                                colors = ListItemDefaults.colors(containerColor = AlertDialogDefaults.containerColor),
                            )
                        }
                    }
                    HorizontalDivider()
                }
            }
        }

        errorDialogStrId?.let { strId ->
            JetPrefAlertDialog(
                title = stringRes(R.string.error__title),
                confirmLabel = stringRes(android.R.string.ok),
                onConfirm = {
                    errorDialogStrId = null
                },
                onDismiss = {
                    errorDialogStrId = null
                },
            ) {
                Text(text = stringRes(strId))
            }
        }
    }
}

@Composable
private fun SubtypeProperty(text: String, content: @Composable () -> Unit) {
    Column(modifier = Modifier.padding(vertical = 8.dp, horizontal = 8.dp)) {
        Text(
            modifier = Modifier.padding(bottom = 8.dp),
            text = text,
            style = MaterialTheme.typography.titleSmall,
        )
        content()
    }
}

@Composable
private fun SubtypeLayoutDropdown(
    layoutType: LayoutType,
    layouts: Map<ExtensionComponentName, LayoutArrangementComponent>,
    showSelectAsError: Boolean,
    layoutMap: SubtypeLayoutMap,
    onLayoutMapChanged: (SubtypeLayoutMap) -> Unit,
    selectListValues: List<String>,
) {
    // 添加常见布局的中文标识 / Add Chinese labels for common layouts
    val layoutChineseNames = mapOf(
        // 字符布局 / Character layouts
        "qwerty" to "QWERTY标准键盘",
        "qwertz" to "QWERTZ德式键盘",
        "azerty" to "AZERTY法式键盘",
        "dvorak" to "Dvorak德沃夏克键盘",
        "colemak" to "Colemak键盘",
        "colemak_dh" to "Colemak DH键盘",
        
        // 符号布局修饰符 / Symbol modifiers
        "default" to "默认",
        "armenian" to "亚美尼亚",
        "cjk" to "中日韩",
        "neo2" to "Neo2",
        "eastern" to "东方",
        "ipa" to "国际音标",
        "persian" to "波斯",
        "western" to "西方",
        "western_samsung" to "西方(三星)",
        
        // 数字和电话布局 / Numeric and phone layouts
        "western_arabic" to "西方阿拉伯数字",
        "eastern_arabic" to "东方阿拉伯数字",
        "telpad" to "拨号键盘",
        
        // 通用 / Generic
        "symbols" to "符号",
        "numeric" to "数字",
        "phone" to "电话"
    )
    
    val layoutIds = remember(layouts) { SelectListKeys + layouts.keys.toList() }
    val layoutLabels = remember(layouts) {
        selectListValues + layouts.map { (key, component) ->
            val chineseName = layoutChineseNames[key.componentId]
            if (chineseName != null) {
                "$chineseName (${component.label})"
            } else {
                component.label
            }
        }
    }
    val layoutId = remember(layoutMap) { layoutMap[layoutType] }
    val expanded = remember { mutableStateOf(false) }
    val selectedIndex = layoutIds.indexOf(layoutId).coerceAtLeast(0)
    JetPrefDropdown(
        options = layoutLabels,
        expanded = expanded,
        selectedOptionIndex = selectedIndex,
        isError = showSelectAsError && selectedIndex == 0,
        onSelectOption = { onLayoutMapChanged(layoutMap.copy(layoutType = layoutType, componentName = layoutIds[it])!!) },
        appearance = JetPrefDropdownMenuDefaults.outlined(shape = ShapeDefaults.Small),
    )
}

@Composable
private fun SubtypeGroupSpacer() {
    Spacer(modifier = Modifier
        .fillMaxWidth()
        .height(32.dp))
}
